home *** CD-ROM | disk | FTP | other *** search
-
-
-
- aaaallllpppp((((7777)))) aaaallllpppp((((7777))))
-
-
-
- NNNNAAAAMMMMEEEE
- _aaaa_llll_pppp - algorithm pool management module
-
- DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
- The STREAMS module _aaaa_llll_pppp maintains a pool of algorithms (in the form of
- STREAMS-compatible subroutines) that may be used for processing STREAMS
- data messages. Interfaces are defined allowing modules to request and
- initiate processing by any of the algorithms maintained in the pool. It
- is expected to help centralize and standardize the interfaces to
- algorithms that now represent a proliferation of similar-but-different
- STREAMS modules. Its major use is envisioned as a central registry of
- available code set conversion algorithms or other types of common data-
- manipulating routines.
-
- An _a_l_g_o_r_i_t_h_m _p_o_o_l is a registry (or _p_o_o_l) of available functions; in this
- case, routines for performing transformations on STREAMS data messages.
- Registered functions may keep information on attached users, which means
- that algorithms need not be stateless, but may maintain extensive state
- information related to each connection. An algorithm from the pool is
- called by another in-kernel module with arguments that are a STREAMS data
- message and a unique identifier. If a message is passed back to the
- caller, it is the algorithm's output, otherwise the algorithm may store
- partially convertible input until enough input is received to give back
- output on a subsequent call.
-
- This pool is one means for providing a consistent and flexible interface
- for _c_o_d_e _s_e_t _c_o_n_v_e_r_s_i_o_n within STREAMS modules, especially _kkkk_bbbb_dddd, but it
- may also be used to provide other services that are commonly duplicated
- by several modules.
-
- The _aaaa_llll_pppp module contains some subroutines dealing with its (minor) role as
- a module, a data definition for an algorithm list, connection and
- disconnection routines, and a search routine for finding registered
- items. The module interface incorporated into _aaaa_llll_pppp serves the purpose of
- providing an _iiii_oooo_cccc_tttt_llll interface, so that users can find out what algorithms
- are registered [see _aaaa_llll_pppp_qqqq(1)].
-
- The programmer of a function for use with _aaaa_llll_pppp provides a simple module
- with a simple specified interface. The module must have an
- initialization routine (_x_x_x_iiii_nnnn_iiii_tttt) which is called at system startup time
- to register itself with _aaaa_llll_pppp, an open routine, and an interface routine
- (which actually implements the algorithm).
-
- The registry method of dynamically building the list of available
- functions obviates the need for recompiling modules or otherwise updating
- a list or reconfiguring other parts of the system to accommodate
- additions or deletions. To install a new function module, one merely
- links it with the kernel in whatever manner is standard for that system;
- there is no need for updating or re-configuring any other parts of the
- kernel (including _aaaa_llll_pppp itself). The remainder of this discussion concerns
- the in-kernel operation and use of the module.
-
-
-
-
- PPPPaaaaggggeeee 1111
-
-
-
-
-
-
- aaaallllpppp((((7777)))) aaaallllpppp((((7777))))
-
-
-
- CCCCaaaalllllllliiiinnnngggg SSSSeeeeqqqquuuueeeennnncccceeee
- An algorithm is called from the pool by first requesting a connection via
- the _aaaa_llll_pppp connection interface. The _aaaa_llll_pppp module returns the function
- address of an interface routine, and fills in a unique identifier (_iiii_dddd)
- for the connection. The returned function address is NULL on failure
- (and _iiii_dddd is undefined). This is a sample of making a connection to a
- function managed by _aaaa_llll_pppp:
- _uuuu_nnnn_ssss_iiii_gggg_nnnn_eeee_dddd _cccc_hhhh_aaaa_rrrr _****_nnnn_aaaa_mmmm_eeee_;;;; _////_**** _aaaa_llll_gggg_oooo_rrrr_iiii_tttt_hhhh_mmmm _nnnn_aaaa_mmmm_eeee _****_////
- _cccc_aaaa_dddd_dddd_rrrr______tttt _iiii_dddd_;;;; _////_**** _uuuu_nnnn_iiii_qqqq_uuuu_eeee _iiii_dddd _****_////
- _mmmm_bbbb_llll_kkkk______tttt _****_((((_****_ffff_uuuu_nnnn_cccc_))))_((((_))))_;;;; _////_**** _ffff_uuuu_nnnn_cccc _rrrr_eeee_tttt_uuuu_rrrr_nnnn_ssss _pppp_oooo_iiii_nnnn_tttt_eeee_rrrr _tttt_oooo _mmmm_bbbb_llll_kkkk______tttt _****_////
- _mmmm_bbbb_llll_kkkk______tttt _****_((((_****_aaaa_llll_pppp______cccc_oooo_nnnn_((((_))))_))))_((((_))))_;;;; _////_**** _rrrr_eeee_tttt_uuuu_rrrr_nnnn_ssss _pppp_oooo_iiii_nnnn_tttt_eeee_rrrr _tttt_oooo _mmmm_bbbb_llll_kkkk______tttt _****_////
- _...._...._....
- _iiii_ffff _((((_ffff_uuuu_nnnn_cccc _==== _aaaa_llll_pppp______cccc_oooo_nnnn_((((_nnnn_aaaa_mmmm_eeee_,,,, _((((_cccc_aaaa_dddd_dddd_rrrr______tttt_)))) _&&&&_iiii_dddd_))))_))))
- _r_e_g_u_l_a_r _p_r_o_c_e_s_s_i_n_g_;;;;
- _eeee_llll_ssss_eeee
- _e_r_r_o_r _p_r_o_c_e_s_s_i_n_g_;;;;
- Once the connection has been made, the interface routine can be called
- directly by the connecting module to process messages:
- _mmmm_bbbb_llll_kkkk______tttt _****_iiii_nnnn_pppp_,,,, _****_oooo_uuuu_tttt_pppp_;;;;
- _mmmm_bbbb_llll_kkkk______tttt _****_((((_****_ffff_uuuu_nnnn_cccc_))))_((((_))))_;;;;
- _...._...._....
- _oooo_uuuu_tttt_pppp _==== _((((_****_ffff_uuuu_nnnn_cccc_))))_((((_mmmm_pppp_,,,, _iiii_dddd_))))_;;;;
- _mmmm_pppp _==== _NNNN_UUUU_LLLL_LLLL_;;;; _////_**** _mmmm_pppp _cccc_aaaa_nnnn_nnnn_oooo_tttt _bbbb_eeee _rrrr_eeee_----_uuuu_ssss_eeee_dddd_!!!! _****_////
- _iiii_ffff _((((_oooo_uuuu_tttt_pppp_))))
- _r_e_g_u_l_a_r _p_r_o_c_e_s_s_i_n_g;
- If the interface routine processed the entire message, then _oooo_uuuu_tttt_pppp is a
- valid pointer to the algorithm's output message. If, however, the
- routine needs more information, or is buffering something, _oooo_uuuu_tttt_pppp will be a
- null pointer. In either case, the original message (_mmmm_pppp) may not be
- subsequently accessed by the caller. The interface routine takes charge
- of the message _mmmm_pppp, and may free it or otherwise dispose of it (it may
- even return the same message). The caller may pass a null message
- pointer to an interface routine to cause a flush of any data being held
- by the routine; this is useful for end-of-file conditions to insure that
- all data have been passed through. (Interface routines must thus
- recognize a null message pointer and deal with it.)
-
- Synchronization between input and output messages is not guaranteed for
- all items in the pool. If one message of input does not produce one
- message of output, this fact should be documented for that particular
- module. Many multibyte code set conversion algorithms, to cite one
- instance, buffer partial sequences, so that if a multibyte character
- happens to be spread across more than one message, it may take two or
- more output messages to complete translation; in this case, it is only
- possible to synchronize when input message boundaries coincide with
- character boundaries.
-
-
-
-
-
- PPPPaaaaggggeeee 2222
-
-
-
-
-
-
- aaaallllpppp((((7777)))) aaaallllpppp((((7777))))
-
-
-
- BBBBuuuuiiiillllddddiiiinnnngggg aaaannnn AAAAllllggggoooorrrriiiitttthhhhmmmm ffffoooorrrr tttthhhheeee PPPPoooooooollll
- As mentioned, the modules managed by _aaaa_llll_pppp are implemented as simple
- modules-not STREAMS modules-each with an initialization routine, an open
- routine, and a user-interface routine. The initialization routine is
- called when the system is booted and prior to nearly everything else that
- happens at boot-time. The routine takes no arguments and its sole
- purpose is to register the algorithm with the _aaaa_llll_pppp module, so that it may
- subsequently accessed. Any other required initialization may also be
- performed at that time. A generic initialization routine for a module
- called _GGGG_EEEE_NNNN, with prefix _gggg_eeee_nnnn is as follows:
- _gggg_eeee_nnnn_iiii_nnnn_iiii_tttt_((((_))))
- _{{{{
- _mmmm_bbbb_llll_kkkk______tttt _****_gggg_eeee_nnnn_ffff_uuuu_nnnn_cccc_((((_))))_;;;; _////_**** _iiii_nnnn_tttt_eeee_rrrr_ffff_aaaa_cccc_eeee _rrrr_oooo_uuuu_tttt_iiii_nnnn_eeee _****_////
- _iiii_nnnn_tttt _rrrr_vvvv_aaaa_llll_;;;; _////_**** _rrrr_eeee_tttt_uuuu_rrrr_nnnn _vvvv_aaaa_llll_uuuu_eeee _ffff_rrrr_oooo_mmmm _rrrr_eeee_gggg_iiii_ssss_tttt_rrrr_aaaa_rrrr _****_////
-
- _rrrr_vvvv_aaaa_llll _==== _aaaa_llll_pppp______rrrr_eeee_gggg_iiii_ssss_tttt_eeee_rrrr_((((_gggg_eeee_nnnn_ffff_uuuu_nnnn_cccc_,,,, _""""_n_a_m_e_""""_,,,, _""""_e_x_p_l_a_n_a_t_i_o_n_""""_))))_;;;;
- _iiii_ffff _((((_rrrr_vvvv_aaaa_llll_)))) _cccc_mmmm_nnnn______eeee_rrrr_rrrr_((((_CCCC_EEEE______WWWW_AAAA_RRRR_NNNN_,,,, _""""_w_a_r_n_i_n_g _m_e_s_s_a_g_e_""""_))))_;;;;
- _}}}}
- The registration routine, _aaaa_llll_pppp______rrrr_eeee_gggg_iiii_ssss_tttt_eeee_rrrr takes three arguments and returns
- zero if successful. The arguments are (1) a pointer to the algorithm's
- entry point (in this case, the function _gggg_eeee_nnnn_ffff_uuuu_nnnn_cccc), (2) a pointer to its
- name, and (3) a pointer to a character string containing a brief
- explanation. The name should be limited to under 16 bytes, and the
- explanation to under 60 bytes, as shown in the following example.
- Neither the name nor the explanation need include a newline.
- _iiii _==== _aaaa_llll_pppp______rrrr_eeee_gggg_iiii_ssss_tttt_eeee_rrrr_((((_ssss_jjjj_iiii_ssss_ffff_uuuu_nnnn_cccc_,,,, _""""_ssss_tttt_oooo_uuuu_""""_,,,, _""""_SSSS_hhhh_iiii_ffff_tttt_----_JJJJ_IIII_SSSS _tttt_oooo _UUUU_JJJJ_IIII_SSSS _cccc_oooo_nnnn_vvvv_eeee_rrrr_tttt_eeee_rrrr_""""_))));
- It is possible for a single module to contain several different, related
- algorithms, which can each be registered separately by a single _iiii_nnnn_iiii_tttt
- routine.
-
- A module's open routine is called by _aaaa_llll_pppp______cccc_oooo_nnnn when a connection is first
- requested by a user (that is, a module that wishes to use it). The open
- routine takes two arguments. The first argument is an integer; if it is
- non-zero, the request is an open request, and the second argument is
- unused. The function should allocate a unique identifier and return it
- as a generic address pointer. If the first argument is zero, the request
- is a close request, and the second argument is the unique identifier that
- was returned by a previous open request, indicating which of (potentially
- several) connections is to be closed. The routine does any necessary
- clean-up and closes the connection; thereafter, any normal interface
- requests on that identifier will fail. This use of unique identifiers
- allows these modules to keep state information relating to each open
- connection; no format is imposed upon the unique identifier, so it may
- contain any arbitrary type of information, equivalent in size to a core
- address; _aaaa_llll_pppp and most callers will treat it as being of type _cccc_aaaa_dddd_dddd_rrrr______tttt, in
- a manner similar to the private data held by each instantiation of a
- STREAMS module.
-
-
-
-
- PPPPaaaaggggeeee 3333
-
-
-
-
-
-
- aaaallllpppp((((7777)))) aaaallllpppp((((7777))))
-
-
-
- A skeleton for the _gggg_eeee_nnnn module's open routine is:
- _gggg_eeee_nnnn_oooo_pppp_eeee_nnnn_((((_aaaa_rrrr_gggg_,,,, _iiii_dddd_))))
- _iiii_nnnn_tttt _aaaa_rrrr_gggg_;;;;
- _cccc_aaaa_dddd_dddd_rrrr______tttt _iiii_dddd_;;;;
- _{{{{
- _iiii_ffff _(((( _aaaa_rrrr_gggg _)))) _{{{{
- _o_p_e_n _p_r_o_c_e_s_s_i_n_g_;;;;
- _rrrr_eeee_tttt_uuuu_rrrr_nnnn_(((( _u_n_i_q_u_e-_i_d _))))_;;;;
- _}}}}
- _c_l_o_s_e _p_r_o_c_e_s_s_i_n_g _f_o_r _iiii_dddd_;;;;
- _rrrr_eeee_tttt_uuuu_rrrr_nnnn_((((_0000_))))_;;;;
- }
- Once a connection has been made, users may proceed as in the example in
- the previous section. When the connection is to be closed (for example,
- the connecting module is being popped), a call is made to _aaaa_llll_pppp______dddd_iiii_ssss_cccc_oooo_nnnn,
- passing the unique id and the name:
- _cccc_aaaa_dddd_dddd_rrrr______tttt _iiii_dddd_;;;;
- _cccc_hhhh_aaaa_rrrr _****_nnnn_aaaa_mmmm_eeee_;;;;
- _mmmm_bbbb_llll_kkkk______tttt _****_aaaa_llll_pppp______dddd_iiii_ssss_cccc_oooo_nnnn_((((_))))_,,,, _****_mmmm_pppp_;;;;
- _...._...._....
- _mmmm_pppp _==== _aaaa_llll_pppp______dddd_iiii_ssss_cccc_oooo_nnnn_((((_nnnn_aaaa_mmmm_eeee_,,,, _iiii_dddd_))))_;;;;
- _iiii_ffff _((((_mmmm_pppp_))))
- _p_r_o_c_e_s_s ``_l_e_f_t-_o_v_e_r'' _d_a_t_a_;;;;
-
- If the disconnect request returns a valid message pointer (_mmmm_pppp) then there
- was unprocessed or partially processed data left in an internal buffer,
- and it should be dealt with by the caller (for example, by flushing it or
- sending it to the neighboring module).
-
- TTTThhhheeee iiiiooooccccttttllll aaaannnndddd QQQQuuuueeeerrrryyyy IIIInnnntttteeeerrrrffffaaaacccceeeessss
- A kernel-level query interface is provided in addition to the query
- interface supported by the _aaaa_llll_pppp_qqqq command. The routine _aaaa_llll_pppp______qqqq_uuuu_eeee_rrrr_yyyy takes a
- single argument, a pointer to a _n_a_m_e. If the name matches a registered
- function, _aaaa_llll_pppp______qqqq_uuuu_eeee_rrrr_yyyy returns a pointer to the function's _e_x_p_l_a_n_a_t_i_o_n
- string, otherwise it returns a null pointer. A calling example is:
- _uuuu_nnnn_ssss_iiii_gggg_nnnn_eeee_dddd _cccc_hhhh_aaaa_rrrr _****_aaaa_llll_pppp______qqqq_uuuu_eeee_rrrr_yyyy_((((_))))_,,,, _****_nnnn_aaaa_mmmm_eeee_,,,, _****_eeee_xxxx_pppp_llll_;;;;
- _...._...._....
- _iiii_ffff _((((_eeee_xxxx_pppp_llll _==== _aaaa_llll_pppp______qqqq_uuuu_eeee_rrrr_yyyy_((((_nnnn_aaaa_mmmm_eeee_))))_))))
- _r_e_g_u_l_a_r _p_r_o_c_e_s_s_i_n_g_;;;;
- _eeee_llll_ssss_eeee
- _e_r_r_o_r _p_r_o_c_e_s_s_i_n_g_;;;;
- The _iiii_oooo_cccc_tttt_llll interface provides calls for querying registered functions (for
- which the _e_x_p_l_a_n_a_t_i_o_n discussed above is necessary); this is supported by
- the _aaaa_llll_pppp_qqqq command, which may be used whenever user-level programs need the
- associated information.
-
-
-
-
- PPPPaaaaggggeeee 4444
-
-
-
-
-
-
- aaaallllpppp((((7777)))) aaaallllpppp((((7777))))
-
-
-
- UUUUsssseeeessss
- The _aaaa_llll_pppp module can be used to replace various kernel-resident code set
- conversion functions in international or multi-language environments.
- The KBD subsystem (which supplies code set conversion and keyboard
- mapping) supports the use of _aaaa_llll_pppp algorithms as processing elements.
-
- Since state information may be maintained, functions may also implement
- processing on larger or more structured data elements, such as
- transaction records and network packets. Currently, STREAMS CPU priority
- is assumed by _aaaa_llll_pppp or should be set individually by interface and open
- routines.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 5555
-
-
-
-
-
-
- aaaallllpppp((((7777)))) aaaallllpppp((((7777))))
-
-
-
- EEEEXXXXAAAAMMMMPPPPLLLLEEEESSSS
- /*
- * This is a SAMPLE module that registers with ALP and performs
- * a one-message delay.
- */
- #include <sys/types.h>
- #include <sys/stream.h>
- #include <sys/stropts.h>
- #include <sys/kmem.h>
- #include <sys/alp.h>
-
- static mblk_t *dely();
- caddr_t delyopen();
-
- /*
- * Our state structure. Keeps its own address and a pointer.
- */
- struct dstruct {
- caddr_t d_unique;
- mblk_t *d_mp;
- };
-
- /*
- * The name is "Dely". It has an open routine "delyopen"
- * and an interface "dely".
- */
- static struct algo delyalgo =
- {
- 0, (queue_t *) 0, (queue_t *) 0, dely, delyopen,
- (unsigned char *) "Dely",
- (unsigned char *) "One Message Delay Buffer",
- (struct algo *) 0
- };
-
- /*
- * This is the sysinit routine, called when the system is
- * being brought up. It registers "Dely" with ALP.
- */
- delyinit()
- {
- if (alp_register(&delyalgo)) /* then register with ALP */
- printf("DELY: register failed\n");
- }
- /*
- * This is the interface routine itself.
- * Holds onto "mp" and returns whatever it had before.
- */
- static mblk_t *
- dely(mp, id)
- mblk_t *mp;
- caddr_t id;
- {
-
-
-
- PPPPaaaaggggeeee 6666
-
-
-
-
-
-
- aaaallllpppp((((7777)))) aaaallllpppp((((7777))))
-
-
-
- register mblk_t *rp;
- register struct dstruct *d;
-
- d = (struct dstruct *) id; /* clarify the situation */
- rp = d->d_mp;
- d->d_mp = mp;
- return(rp); /* return the previous message */
- }
-
- /*
- * The open (and close) routine. Use kmem_alloc() to get a private
- * structure for saving state info.
- */
- caddr_t
- delyopen(arg, id)
- int arg; /* 1 = open, 0 = close */
- caddr_t id; /* ignored on open; is unique id on close */
- {
- register struct dstruct *d;
- register mblk_t *rp;
-
- if (! arg) { /* close processing */
- d = (struct dstruct *) id;
- d->d_unique = (caddr_t) -1;
- rp = d->d_mp;
- kmem_free(d, sizeof(struct dstruct));
- return((caddr_t) rp);
- }
- /* otherwise, open processing */
- d = (struct dstruct *) kmem_zalloc(sizeof(struct dstruct),
- KM_NOSLEEP);
- d->d_unique = (caddr_t) &d;
- return((caddr_t) d);
- }
-
- SSSSEEEEEEEE AAAALLLLSSSSOOOO
- _aaaa_llll_pppp_qqqq(1), _kkkk_bbbb_dddd(7).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- PPPPaaaaggggeeee 7777
-
-
-
-